# Copyright (C) 2008 Thibauld Favre <tfavre@gmail.com>
# This module is a derived work from the python flickrapi that can
# be found at http://flickrapi.sf.net/
#
# Copyright (c) 2007 by the respective coders, see
# http://flickrapi.sf.net/
#
# This code is subject to the Python licence, as can be read on
# http://www.python.org/download/releases/2.5.2/license/
#
# For those without an internet connection, here is a summary. When this
# summary clashes with the Python licence, the latter will be applied.
#
# Permission is hereby granted, free of charge, to any person obtaining
# a copy of this software and associated documentation files (the
# "Software"), to deal in the Software without restriction, including
# without limitation the rights to use, copy, modify, merge, publish,
# distribute, sublicense, and/or sell copies of the Software, and to
# permit persons to whom the Software is furnished to do so, subject to
# the following conditions:
#
# The above copyright notice and this permission notice shall be
# included in all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
# IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
# CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

import os.path
import smcagent
from M2Crypto import X509, SMIME
from smcagent.xmlnode import XMLNode

class TokenCache(object):
    """On-disk persistent token cache for a single application.
    The application is identified by the API key used.
    """
    
    def __init__(self, api_key):
        """Creates a new token cache instance"""
        self.api_key = api_key
	self.config_cache = os.path.expanduser(os.path.join(smcagent.config_cache,self.api_key))
        
    def __getCachedTokenPath(self):
        """Return the directory holding the app data."""
	return self.config_cache

    def __getCachedTokenFilename(self):
        """Return the full pathname of the cached token file."""
        return os.path.join(self.__getCachedTokenPath(), "auth.xml")

    def __getCachedSecret(self):
        """Read and return a cached secret, or None if not found.
        The secret is read from the cached token file, which is basically the
        entire RSP response containing the token and secret element.
	"""
	try:
            f = file(self.__getCachedTokenFilename(), "r")
            data = f.read()
            f.close()
            rsp = XMLNode.parseXML(data)
            return rsp.secret[0].elementText
        except Exception:
            return None

    def __getCachedToken(self):
        """Read and return a cached token, or None if not found.
        The token is read from the cached token file, which is basically the
        entire RSP response containing the auth element.
        """

        try:
            f = file(self.__getCachedTokenFilename(), "r")
            data = f.read()
            f.close()
            rsp = XMLNode.parseXML(data)
            return rsp.token[0].elementText
        except:
            return None

    def __setCachedToken(self, token_xml):
        """Cache a token for later use.
        The cached tag is stored by simply saving the entire RSP response
        containing the auth element.
        """

        path = self.__getCachedTokenPath()
        if not os.path.exists(path):
            os.makedirs(path)

        f = file(self.__getCachedTokenFilename(), "w")
        f.write(token_xml)
        f.close()

    def __delCachedToken(self):
        """Removes the cached token"""
        os.unlink(self.__getCachedTokenFilename())
        
    token = property(__getCachedToken, __setCachedToken, __delCachedToken, "The cached token")
    secret = property(__getCachedSecret, "The cached secret")

class CertificateCache(object):
    """On-disk persistent certificate cache for a single application.
    The application is identified by the API key used.
    """

    def __init__(self, api_key):
        """Creates a new token certificate instance"""
        self.api_key = api_key
	self.config_cache = os.path.expanduser(os.path.join(smcagent.config_cache,self.api_key))
        
    def __getCachedCertificatePath(self):
        """Return the directory holding the app data."""
	return self.config_cache

    def __getCachedCertificateFilename(self):
        """Return the full pathname of the cached certificate file."""
        return os.path.join(self.__getCachedCertificatePath(), "code.crt")

    def __getCachedCertificate(self):
        """Read and return the cached code certificate, or None if not found.
        The secret is read from the cached certificate file.
	"""
	try:
		smime = SMIME.SMIME()
		x509 = X509.load_cert(self.__getCachedCertificateFilename())
		sk = X509.X509_Stack()
		sk.push(x509)
		smime.set_x509_stack(sk)
		st = X509.X509_Store()
		st.load_info(self.__getCachedCertificateFilename())
		smime.set_x509_store(st)
		return smime
        except:
            	return None

    def __setCachedCertificate(self, certificate_plain):
        """Cache a certificate for later use."""

        path = self.__getCachedCertificatePath()
        if not os.path.exists(path):
            os.makedirs(path)

        f = file(self.__getCachedCertificateFilename(), "w")
        f.write(certificate_plain)
        f.close()

    def __delCachedCertificate(self):
        """Removes the cached certificate"""
        os.unlink(self.__getCachedCertificateFilename())

    certificate = property(__getCachedCertificate, __setCachedCertificate, __delCachedCertificate, "The code certificate")
